/**
 * @author amalafe
 */

Namespace("sketch.decorators");

(function($) {
    // usings
    var dec = sketch.decorators,
        fwk = sketch.framework;

    dec.ActiveFrame = klass(fwk.UIElementDecorator, (function() {
        var PointSize = 6;
        var PointSize2 = 3;
        var PannelSize = 8;
        var PannelSize2 = 4;

        var updatePosition = function(that) {
            var rect = that.element.getBoundaryRectGlobal();

			that.pannel.left(rect.x - that.margin);
	 		that.pannel.top(rect.y - that.margin);
	 		that.pannel.width((rect.width + 2 * that.margin));
	 		that.pannel.height((rect.height + 2 * that.margin));
	 		that.pannel.zOrder(that.element.zOrder() - 1);

            that.resizePoints.each(function(idx, pt) {
                pt.div.left(pt.x());
                pt.div.top(pt.y());
            });

            that.resizePannels.each(function(idx, pannel) {
                pannel.div.left(pannel.x());
                pannel.div.top(pannel.y());
                pannel.div.width(pannel.w());
                pannel.div.height(pannel.h());
            });
        };

        var createResizePoints = function() {
            var that = this;
            var l = function() {
                    return that.rect.x - PointSize2;
                },
                m = function() {
                    return that.rect.x + that.rect.width / 2 - PointSize2;
                },
                r = function() {
                    return that.rect.x + that.rect.width - PointSize2;
                },
                t = function() {
                    return that.rect.y - PointSize2;
                },
                hm = function() {
                    return that.rect.y + that.rect.height / 2 - PointSize2;
                },
                b = function() {
                    return that.rect.y + that.rect.height - PointSize2;
                },
                div = function() {
                    return new ResizePoint()
                };
            this.resizePoints = $([]);
            var resizeDimensions = this.element.resizeDimensions();
            if ((resizeDimensions & fwk.ResizeDimension.Both) === fwk.ResizeDimension.Both) {
                this.resizePoints.push({ div:div(), x:l, y:t });
                this.resizePoints.push({ div:div(), x:r, y:t });
                this.resizePoints.push({ div:div(), x:r, y:b });
                this.resizePoints.push({ div:div(), x:l, y:b });
            }

            if ((resizeDimensions & fwk.ResizeDimension.Vertical) === fwk.ResizeDimension.Vertical) {
                this.resizePoints.push({ div:div(), x:m, y:t });
                this.resizePoints.push({ div:div(), x:m, y:b });
            }

            if ((resizeDimensions & fwk.ResizeDimension.Horizontal) === fwk.ResizeDimension.Horizontal) {
                this.resizePoints.push({ div:div(), x:r, y:hm });
                this.resizePoints.push({ div:div(), x:l, y:hm });
            }

//

            this.resizePoints.each(function(idx, pt) {
                pt.div.width(PointSize);
                pt.div.height(PointSize);
            });
        };

        var createResizePannels = function() {
            var that = this;
            var l = function() {
                return that.rect.x - PannelSize2;
            },
                m = function() {
                    return that.rect.x + that.rect.width / 2 - PannelSize2;
                },
                r = function() {
                    return that.rect.x + that.rect.width - PannelSize2;
                },
                t = function() {
                    return that.rect.y - PannelSize2;
                },
                hm = function() {
                    return that.rect.y + that.rect.height / 2 - PannelSize2;
                },
                b = function() {
                    return that.rect.y + that.rect.height - PannelSize2;
                },
                div = function() {
                    return new ResizePannel();
                },
                cs = function() {
                    return PannelSize;
                },
                fw = function() {
                    return that.rect.width;
                },
                fh = function() {
                    return that.rect.height;
                };
            this.resizePannels = $([]);
            var resizeDimensions = this.element.resizeDimensions();
            if ((resizeDimensions & fwk.ResizeDimension.Horizontal) === fwk.ResizeDimension.Horizontal) {
                this.resizePannels.push({ div:div(), x:l, y:t, w:cs, h:fh, type:"e-resize", move : function(x, y) {
                    var dx = that.rect.x - x;
                    var right = that.rect.x + that.rect.width;
                    var mw = that.element.minWidth();
                    that.rect.width = that.rect.width + dx;

                    if (that.rect.width < mw) {
                        that.rect.width = mw;
                        that.rect.x = right - mw;
                    } else {
                        that.rect.x = x;
                    }
                }
                });
                this.resizePannels.push({ div:div(), x:r, y:t, w:cs, h:fh, type:"e-resize" , move : function(x, y) {
                    var w = x - that.rect.x;
                    var mw = that.element.minWidth();
                    if (w < mw) {
                        w = mw;
                    }
                    that.rect.width = w;
                }
                });
            }

            if ((resizeDimensions & fwk.ResizeDimension.Vertical) === fwk.ResizeDimension.Vertical) {
                this.resizePannels.push({ div:div(), x:l, y:t, w:fw, h:cs, type:"n-resize" , move : function(x, y) {
                    var dy = that.rect.y - y;
                    var bottom = that.rect.y + that.rect.height;
                    var mh = that.element.minHeight();
                    that.rect.height = that.rect.height + dy;

                    if (that.rect.height < mh) {
                        that.rect.height = mh;
                        that.rect.y = bottom - mh;
                    } else {
                        that.rect.y = y;
                    }
                }
                });

                this.resizePannels.push({ div:div(), x:l, y:b, w:fw, h:cs, type:"n-resize" , move : function(x, y) {
                    var h = y - that.rect.y;
                    var mh = that.element.minHeight();
                    if (h < mh) {
                        h = mh;
                    }
                    that.rect.height = h;
                }
                });
            }
            if ((resizeDimensions & fwk.ResizeDimension.Both) === fwk.ResizeDimension.Both) {
                this.resizePannels.push({ div:div(), x:l, y:t, w:cs, h:cs, type:"nw-resize" , move : function(x, y) {
                    var dx = that.rect.x - x;
                    var right = that.rect.x + that.rect.width;
                    var mw = that.element.minWidth();
                    that.rect.width = that.rect.width + dx;

                    if (that.rect.width < mw) {
                        that.rect.width = mw;
                        that.rect.x = right - mw;
                    } else {
                        that.rect.x = x;
                    }

                    var dy = that.rect.y - y;
                    var bottom = that.rect.y + that.rect.height;
                    var mh = that.element.minHeight();
                    that.rect.height = that.rect.height + dy;

                    if (that.rect.height < mh) {
                        that.rect.height = mh;
                        that.rect.y = bottom - mh;
                    } else {
                        that.rect.y = y;
                    }
                }
                });
                this.resizePannels.push({ div:div(), x:r, y:b, w:cs, h:cs, type:"nw-resize" , move : function(x, y) {
                    var w = x - that.rect.x;
                    var mw = that.element.minWidth();
                    if (w < mw) {
                        w = mw;
                    }
                    that.rect.width = w;

                    var h = y - that.rect.y;
                    var mh = that.element.minHeight();
                    if (h < mh) {
                        h = mh;
                    }
                    that.rect.height = h;
                }
                });
                this.resizePannels.push({ div:div(), x:r, y:t, w:cs, h:cs, type:"ne-resize" , move : function(x, y) {
                    var w = x - that.rect.x;
                    var mw = that.element.minWidth();
                    if (w < mw) {
                        w = mw;
                    }
                    that.rect.width = w;

                    var dy = that.rect.y - y;
                    var bottom = that.rect.y + that.rect.height;
                    var mh = that.element.minHeight();
                    that.rect.height = that.rect.height + dy;
                    if (that.rect.height < mh) {
                        that.rect.height = mh;
                        that.rect.y = bottom - mh;
                    } else {
                        that.rect.y = y;
                    }
                }
                });
                this.resizePannels.push({ div:div(), x:l, y:b, w:cs, h:cs, type:"ne-resize" , move : function(x, y) {
                    var dx = that.rect.x - x;
                    var right = that.rect.x + that.rect.width;
                    var mw = that.element.minWidth();
                    that.rect.width = that.rect.width + dx;

                    if (that.rect.width < mw) {
                        that.rect.width = mw;
                        that.rect.x = right - mw;
                    } else {
                        that.rect.x = x;
                    }

                    var h = y - that.rect.y;
                    var mh = that.element.minHeight();
                    if (h < mh) {
                        h = mh;
                    }
                    that.rect.height = h;
                }
                });
            }

            this.resizePannels.each(function(idx, pannel) {
                pannel.div.cursor(pannel.type);
                pannel.div.mousedown.bind(function(event) {
                    event.handled = true;
                    pannel.div.captureMouse();
                    that.holdLeftButton = true;
                    startResizing.call(that);
                    that.element.invalidate();
                });

                pannel.div.mouseup.bind(function(event) {
                    event.handled = true;
                    pannel.div.releaseMouse();
                    that.holdLeftButton = false;
                    that.element.invalidate();
                    stopResizing.call(that);
                });

                pannel.div.mousemove.bind(EventHandler(pannel, function(event) {
                    event.handled = true;

                    if (that.holdLeftButton) {
                        this.move(event.x, event.y);
                        that.updateFromRect();
                        that.element.invalidate();
                    }
                }));
            });
        };

        var startResizing = function() {
            this._resizingElement = new fwk.DraggingElement(this.element);
            this.rect = this.element.getBoundaryRectGlobal();
            this.element.view().layer3.add(this._resizingElement);
        };

        var stopResizing = function() {
            //sometimes mouseup comes without mousedown
            if (this._resizingElement) {
                this._resizingElement.detach(null, this.element.parent());
            }
        };

        var parentChanged = function() {
            this.rect = this.element.getBoundaryRectGlobal();
            updatePosition(this);
        };

        return {
            __type__:"framework.ActiveFrame",
            _constructor : function() {
                this.margin = 0;

            },
            attach : function(element) {
                dec.ActiveFrame.Super.attach.call(this, element);

                var that = this;
                var parent = element.parent();
                var view = parent.view();

                createResizePoints.call(this);
                createResizePannels.call(this);
                this.pannel = new Background();
                this.parentChanged = EventHandler(this, parentChanged);

                this.pannel.zOrder(element.zOrder() - 1);
                view.layer3.add(this.pannel);
                this.rect = this.element.getBoundaryRectGlobal();
                updatePosition(this);

                this.resizePoints.each(function(idx, pt) {
                    pt.div.zOrder(Number.MAX_VALUE);
                    pt.div.visible(true);
                    view.layer3.add(pt.div);
                });

                this.resizePannels.each(function(idx, pannel) {
                    pannel.div.zOrder(that.element.zOrder() + 1);
                    pannel.div.visible(true);
                    view.layer3.add(pannel.div);
                });

                this.element.properties.propertyChanged.bind(this.parentChanged);
            },
            detach : function() {
                dec.ActiveFrame.Super.detach.call(this);

                var parent = this.element.parent();
                var view = parent.view();

                view.layer3.remove(this.pannel);

                this.resizePoints.each(function(idx, pt) {
                    view.layer3.remove(pt.div);
                    pt.div.visible(false);
                });

                this.resizePannels.each(function(idx, pannel) {
                    view.layer3.remove(pannel.div);
                    pannel.div.visible(false);
                });

                this.element.properties.propertyChanged.unbind(this.parentChanged);
            },
            updateFromRect:function() {
                var rect = this._resizingElement.parent().global2local(this.rect);
                rect.width = this.rect.width;
                rect.height = this.rect.height;

                this._resizingElement.resize(rect);
                this._resizingElement.invalidate();
            }
        }
    })());

    var ResizePoint = klass(fwk.ImageElement, {
        _constructor:function() {
            this.src('/img/resize_circle.png');
            this.canScaleSize(false);
        },
        getSnapPoints:function() {
            return null;
        },
        hitTest:function() {
            return false;
        },
        canMultiSelect : function() {
            return false;
        }
    });

    var Background = klass(fwk.Rectangle, {
        _constructor:function(){
            this.fillStyle('rgba(156, 190, 229, 0.5)');
        },
        getSnapPoints:function(){
            return {xs:[], ys:{}};
        },
        hitTest:function(){
            return false;
        },
        canMultiSelect : function(){
            return false;
        },
        isSystem:function(){
            return true;
        }
    });

    var ResizePannel = klass(fwk.Rectangle, {
        _constructor:function() {
            this.mousedown = fwk.EventHelper.createEvent();
            this.mouseup = fwk.EventHelper.createEvent();
            this.mousemove = fwk.EventHelper.createEvent();
            this._cursor = null;
        },
        getSnapPoints:function() {
            return null;
        },
        canMultiSelect : function() {
            return false;
        },
        cursor:function(value) {
            if (arguments.length === 1) {
                this._cursor = value;
            }

            return this._cursor;
        }
    });

})(jQuery);
